home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-07 / lanbook.zip / LAN.C < prev    next >
C/C++ Source or Header  |  1991-09-22  |  19KB  |  711 lines

  1. /*
  2. // LAN.C    LAN information utility
  3. //
  4. // (c) Copyright 1990, 1991 Adrian King.
  5. //
  6. //
  7. //        This code was developed for inclusion in the book
  8. //        "Running LANtastic", by Adrian King, published by
  9. //        Bantam Books, October 1991.
  10. //
  11. //    This product uses the TesSeRact(tm) Ram-Resident Library and
  12. //    supports the TesSeRact Standard for Ram-Resident Program Comm-
  13. //    unication. For information about TesSeRact, contact the TesSeRact
  14. //    Development Team at:
  15. //
  16. //        TesSeRact Development Team
  17. //        1657 The Fairways
  18. //        Suite 101
  19. //        Jenkintown PA 19046
  20. //        1-215-884-3373
  21. //
  22. //        Compuserve:    70731,20
  23. //        MCIMAIL:    315-5415
  24. //
  25. // This is the main module for the foreground program. It analyzes
  26. // the command and parameters, and generates any necessary network
  27. // messages and display output.
  28. //
  29. // LANRES must be loaded before some functions will work.
  30. //
  31. // Make sure to compile this program with a -DFOREGROUND switch.
  32. //
  33. // $Header:   C:/USR/LANBOOK/SRC2/LAN/VCS/LAN.C_V   1.3   22 Sep 1991  9:15:54  $
  34. //
  35. // $Log:   C:/USR/LANBOOK/SRC2/LAN/VCS/LAN.C_V  $
  36.  * 
  37.  *    Rev 1.3   22 Sep 1991  9:15:54
  38.  * Added correct TesSeRact copyright notice.
  39.  * 
  40.  *    Rev 1.2   22 Sep 1991  9:00:42
  41.  * Added the ability to terminate LAN SYNC by pressing a key.
  42. // 
  43. //    Rev 1.1   29 Aug 1991 12:42:36
  44. // Modification to screen layout of LAN STATUS
  45. // 
  46. //    Rev 1.0   13 Jul 1991 11:12:58
  47. // Initial revision.
  48. //
  49. */
  50.  
  51.     // Standard DOS includes
  52.  
  53. #include "stdio.h"
  54. #include "conio.h"
  55. #include "process.h"
  56. #include "dos.h"
  57. #include "string.h"
  58. #include "ctype.h"
  59.  
  60.     // NOS specific includes
  61.  
  62. #include "nos.h"
  63. #include "noslib.h"
  64. #include "lan.h"
  65.  
  66.     // Includes for TesSeRact interface
  67.  
  68. #include "tess.h"
  69.  
  70.     // Forward declarations
  71.  
  72. extern void far lansync();                // Command processing routines
  73. extern void far lanboot();
  74. extern void far lanstatus();
  75. extern void far lansend();
  76. extern void far lanhelp();
  77.  
  78. extern struct lancmd *parsecmd();        // Parse command line
  79. extern int argival();                     // Get integer value of argument
  80. extern char *argsval();                     // Get string value of argument
  81. extern void far reboot();                 // Reboot the machine
  82. extern void getnodetable();                // Get node table from LANRES
  83.  
  84.     // Local defines
  85.  
  86. #define ARGVALERR    -32767
  87.  
  88.     // Global data
  89.  
  90. char cpMyname[] = "FIFTEENCHRACTRS";    // Set to this machine's name
  91.  
  92.     //
  93.     // Command table. Switch through this to carry out a specific
  94.     // LAN program function.
  95.     //
  96.  
  97. struct lancmd {
  98.     char *cpCmd;                    // Pointer to LAN function name
  99.     BOOL bNeedLib;                    // TRUE if LANLIB must be loaded
  100.                                     // for this function, FALSE if not
  101.     FARPROC fpFunc;                    // Pointer to routine that executes 
  102.                                     // this function
  103. };
  104.  
  105. struct lancmd lancmd [] = {            // Table of recognised commands
  106.  
  107.     "SYNC",     FALSE,    lansync,    // Synchronize the LAN
  108.     "BOOT",     FALSE,    lanboot,    // Reboot the LAN
  109.     "STATUS",     TRUE,    lanstatus,    // Get status of LAN
  110.     "SEND",        FALSE,    lansend,    // Broadcast a message to the LAN
  111.     "HELP",        FALSE,    lanhelp,    // Print some help
  112.     "?",        FALSE,    lanhelp,
  113.     "/?",        FALSE,    lanhelp,
  114.     (char *)0,    FALSE,    (FARPROC)0    // Null entry to terminate table
  115. };
  116.  
  117.     //
  118.     // MAIN
  119.     //
  120.  
  121. void main(argc, argv, envp)
  122. int argc;
  123. char *argv[];
  124. char *envp[];
  125. {
  126.     char *cp;
  127.     BOOL bName;
  128.     int  m, n;
  129.     struct lancmd *lc;
  130.  
  131.     printf("LAN version 1.0 - (C) Copyright 1991 Adrian King\n"); 
  132.  
  133.     if (argc == 1)                        // No arguments?
  134.         lanhelp((char *)0);                // Print help and quit.
  135.  
  136.     lc = parsecmd(argv[1]);                   // Find out which command
  137.  
  138.     if (lc->cpCmd == (char *)0)            // Print help if unrecognizable
  139.         lanhelp((char *)0);
  140.  
  141.     n = NOSPresence();                    // Check LANBIOS and REDIR present
  142.     if ((n == -1)||((n & D_redir) == 0))
  143.         FATAL(E_NOLAN);
  144.  
  145.     if (NOSGetMachineName(cpMyname, &m, &bName) == -1)
  146.         FATAL(E_GETNAME);
  147.  
  148.     if (!bName)                            // Name must be set
  149.         FATAL(E_NONAME);
  150.  
  151.     initnodetable();                    // Clear network node table
  152.  
  153.     cp = strchr(cpMyname, ' ');
  154.     if (cp != NULL)
  155.         *cp = '\0';                        // Null terminate the name
  156.  
  157.     addname(cpMyname, n);                // Add name to local table
  158.                                         // (Must always be entry 0.)
  159.  
  160.                                         // Call command processor.
  161.                                         // Do not pass LAN FUNC arguments
  162.     (lc->fpFunc)(lc, argc-2,&argv[2], envp);
  163.  
  164.     exit(0);    // Normal exit
  165. }
  166.  
  167.     //                        
  168.     //    PRINTHELP
  169.     //
  170.     //    Print help text
  171.     //
  172.  
  173. void printhelp(cp)
  174. char *cp;
  175. {
  176.         // Print command specific help if called with an argument
  177.  
  178.     if (cp != (char *)0){
  179.         printf("LAN: Help for %s not yet available\n", cp);
  180.         exit(0);
  181.     }
  182.  
  183.         // Otherwise print general help
  184.  
  185.     printf("\n\
  186. Available commands for LAN are:\n\n\
  187.     LAN HELP or LAN /?                          Display this help message\n\
  188.     LAN SEND Message                            Broadcast a message\n\
  189.     LAN SYNC [/HOST=name]                       Synchronize hosts\n\
  190.     LAN BOOT [/BOOT=[warm|cold]] [/HOST=name]   Reboot the network\n\
  191.     LAN STATUS                                  Show network status\n\
  192. ");
  193. }
  194.  
  195.     //
  196.     //    LANHELP
  197.     //
  198.     //    Command processor for LAN HELP, LAN HELP Command, LAN ? and LAN /?
  199.     //
  200.     //    Arguments are passed but never used
  201.     //
  202.  
  203. void far lanhelp()
  204. {
  205.     printhelp((char *)0);    // Call general help and quit
  206.     exit(0);
  207. }
  208.  
  209.     //
  210.     //    LANSYNC
  211.     //
  212.     //    Command processor for LAN SYNC [/TIMEOUT=timeout] host [host...]
  213.     //
  214.  
  215. void far lansync(lcp, argc, argv)
  216. struct lancmd *lcp;
  217. int argc;
  218. char *argv[];
  219. {
  220.     int timeout;            // Timeout while trying to sync
  221.     int nHosts;                // Number of hosts to sync with
  222.     int i, j;
  223.     int nAdapter;
  224.     char cpNode[D_NAMESZ];
  225.     BOOL bSynced;    
  226.     struct message_buffer m;
  227.  
  228.     if (lcp->bNeedLib)        // Check resident library is there if we need it
  229.         lanlibcheck();
  230.  
  231.     timeout = argival("/TIMEOUT", argc, argv);    // Look for timeout value
  232.  
  233.     if (timeout != ARGVALERR){                    // Found?
  234.         if (argc == 1)                            // Yes. 
  235.             FATAL(E_NOHOST);                    // But no host specified.
  236.         else
  237.             nHosts = argc - 1;                    // Set # of hosts
  238.     } else {
  239.             // Couldn't find the /TIMEOUT argument so set it to default
  240.         timeout = D_TIMEOUT;
  241.         nHosts = argc;                            // Set # of hosts
  242.     }
  243.                                                 // Collect node names
  244.                                                 // for syncing
  245.     while ((timeout > 0) && (nHosts > 0)){
  246.         bSynced = FALSE;
  247.                             // Scan through all command arguments each time
  248.         for (i = 0; i < argc; i++){
  249.                             // Ignore /TIMEOUT argument and any host
  250.                             // names that were already found
  251.             if ((argv[i][0] != '/') && (argv[i][0] != '\0')){
  252.                 printf("Trying to sync with host %s inside %d seconds, press any key to abort...\n",
  253.                         argv[i], timeout);
  254.  
  255.                             // Check if its a self sync...
  256.                 if (nodenamecmp(lannode[0].cpName, argv[i]) == 0){
  257.                     printf("Found host %s\n", argv[i]);
  258.                         // Null it so we don't look at it again
  259.                     argv[i][0] = '\0';
  260.                     nHosts--;
  261.                     continue;
  262.                 }
  263.  
  264.                 j = 0;        // First check all the current logins
  265.                 while (NOSGetLogin(&j, cpNode, &nAdapter) != -1){
  266.                     if (nodenamecmp(cpNode, argv[i]) == 0){
  267.                         printf("Found host %s\n", argv[i]);
  268.                             // Null it so we don't look at it again
  269.                         argv[i][0] = '\0';
  270.                         nHosts--;
  271.                         bSynced = TRUE;
  272.                         break;
  273.                     }
  274.                     j++;
  275.                 };
  276.                             // Move on if we're already synced
  277.                 if (bSynced)    
  278.                     continue;
  279.                             // Check other available servers
  280.                 j = 0;
  281.                 while (NOSGetServer(&j, cpNode, &nAdapter) != -1){
  282.                     if (nodenamecmp(cpNode, argv[i]) == 0){
  283.                         printf("Found host %s\n", argv[i]);
  284.                             // Null it so we don't look at it again
  285.                         argv[i][0] = '\0';
  286.                         nHosts--;
  287.                         bSynced = TRUE;
  288.                         break;
  289.                     }
  290.                     j++;
  291.                 };
  292.                             // Move on if we're synced
  293.                 if (bSynced)
  294.                     continue;
  295.                             // Machine doesn't appear to be available
  296.                             // as a server. We could send a message and
  297.                             // see if it responds. However, if it's a
  298.                             // server just booting up we'll cause popups
  299.                             // every second - bad idea.
  300.             }
  301.  
  302.             if (kbhit()){    // Don't look at this server again if a key
  303.                             // has been pressed
  304.                 (void)getch();
  305.                 argv[i][0] = '\0';
  306.                 nHosts--;
  307.             }
  308.         }
  309.         delay(1000);        // Wait for 1 second before trying again
  310.         timeout--;
  311.     }
  312.     exit(nHosts);            // Exit code is zero if all synced, 
  313.                             // non-zero otherwise
  314. }
  315.  
  316.     //
  317.     //    LANSEND
  318.     //
  319.     //    Command processor for LAN SEND Message
  320.     //
  321.  
  322. void far lansend(lcp, argc, argv)
  323. struct lancmd *lcp;
  324. int argc;
  325. char *argv[];
  326. {
  327.     int i;
  328.     struct message_buffer M;
  329.  
  330.     if (lcp->bNeedLib)        // Check resident library is there if we need it
  331.         lanlibcheck();
  332.  
  333.     if (argc == 0){
  334.         printhelp("SEND");    // No parameters, assume it's an error
  335.         exit(1);
  336.     }
  337.  
  338.         //           
  339.         //    NOTES:
  340.         //
  341.         //    Should add multiple adapter support
  342.         //    
  343.         //    Could add a parameter that says broadcast only to logged
  344.         //    in users rather than the entire network.
  345.         //
  346.  
  347.                             // Send the message with a null machine name.
  348.                             // Everyone will get it.
  349.     if (sendmessage(&M, "", MBT_LANtext, argv[0], strlen(argv[0])) == -1)
  350.         NOSperror("LAN - error sending LAN message");
  351. }
  352.  
  353.     //
  354.     //    LANBOOT
  355.     //
  356.     //    Command processor for LAN BOOT [/BOOT=warmboot|coldboot] [host]
  357.     //
  358.     //    host parameter is of the form /HOST=MACHINE to boot just MACHINE
  359.     //    or NAME1 NAME2 NAME3... in order to boot a list of hosts.
  360.     //
  361.     //    No parameter means boot this machine. When we boot ourselves we
  362.     //    send ourselves a message so that if remote booting has been
  363.     //    disabled we take account of that.
  364.     //
  365.     //    The special name NETWORK means reboot the whole network
  366.     //
  367.  
  368. void far lanboot(lcp, argc, argv)
  369. struct lancmd *lcp;
  370. int argc;
  371. char *argv[];
  372. {
  373.     char *cpHost;            // Name of host to boot
  374.     char *cpBoot;            // Warm or cold boot
  375.     int nHosts;                // # of hosts to go boot
  376.     int i;
  377.     int nBoot;                // Type of boot
  378.     struct message_buffer M;// Message buffer to use
  379.  
  380.     if (lcp->bNeedLib)        // Check resident library is there if we need it
  381.         lanlibcheck();
  382.                             // Check for warm or cold boot. Default is warm.
  383.     cpBoot = argsval("/BOOT", argc, argv);
  384.                             // Reduce arg count if we found the string
  385.     if (cpBoot != NULL)
  386.         argc--;
  387.  
  388.     if (stricmp(cpBoot, "COLD") == 0){
  389.         nBoot = MBT_LANcoldboot;
  390.         cpBoot = "COLD Reboot requested";
  391.     } else {
  392.         nBoot = MBT_LANwarmboot;
  393.         cpBoot = "WARM Reboot requested";
  394.     }
  395.  
  396.                                      // Get the name of the host to go boot
  397.     cpHost = argsval("/HOST", argc, argv);
  398.  
  399.     if (cpHost != NULL){            // Found a /HOST specification?
  400.                                     // Yes, do we mean the whole network?
  401.         if (stricmp(cpHost, "NETWORK") == 0)
  402.             nHosts = -1;            // Yes
  403.         else {                        
  404.             nHosts = 1;                // One host only
  405.         }
  406.     } else {
  407.         if (argc == 0){                // No /HOST switch. If there are no 
  408.             nHosts = 1;                // parameters we boot just ourselves
  409.             cpHost = lannode[0].cpName;
  410.         } else {
  411.             nHosts = argc;            // Assume all parameters are host names
  412.             cpHost = argv[0];        // Set up first host name.
  413.         }
  414.     }
  415.  
  416.     switch (nHosts){
  417.         case 1:                         // Boot one named host
  418.             if (sendmessage(&M, cpHost, nBoot, cpBoot, strlen(cpBoot)) == -1)
  419.                 FATAL(E_MSGERR);
  420.             break;
  421.  
  422.         case -1:                    // Boot the network
  423.             if (sendmessage(&M, "", nBoot, cpBoot, strlen(cpBoot)) == -1)
  424.                 FATAL(E_MSGERR);
  425.             break;
  426.         
  427.         default:
  428.             for (i = 0; i < nHosts; i ++)
  429.                 if (argv[i][0] != '/'){
  430.                      if (sendmessage(&M, argv[i], nBoot, cpBoot, 
  431.                                         strlen(cpBoot)) == -1)
  432.                         FATAL(E_MSGERR);
  433.                 } else 
  434.                     i--;            // Horrible hack to allow /TIMEOUT
  435.                                     // argument to be anywhere on the
  436.                                     // command line.
  437.     }
  438. }
  439.  
  440.     //
  441.     //    LANSTATUS
  442.     //
  443.     //    Command processor for LAN STATUS, a more comprehensive
  444.     //    form of LANSHOW or NET SHOW.
  445.     //
  446.  
  447. void far lanstatus(lcp)
  448. struct lancmd *lcp;
  449. {
  450.     int i, j;
  451.     char cpServer[D_NAMESZ+2], cpUsername[D_NAMESZ];
  452.     struct logical_stream s;
  453.     struct PS ps;
  454.     char *printers[5] = { "LPT1", "LPT2", "LPT3", "COM1", "COM2" };
  455.     BOOL b = FALSE;
  456.  
  457.     if (lcp->bNeedLib)                // Check resident library is there 
  458.         lanlibcheck();
  459.  
  460.         //
  461.         // This causes a broadcast asking for all the network nodes
  462.         // to respond. The responses will be collected in the 
  463.         // background by LANRES. By the time we get to the end of 
  464.         // this routine we should have all the responses. This is,
  465.         // of course, unreliable and running LAN STATUS twice in
  466.         // succession may give you different results.
  467.         //
  468.  
  469.     refreshnames();
  470.  
  471.     j = NOSGetVersion();            // Get and report NOS version number
  472.                                     // and machine name
  473.     printf("\nLANtastic version %d.%02d running on \\\\%s\n\n", 
  474.                 j>>8, j&0xFF, lannode[0].cpName);
  475.  
  476.                                     // Report our own status
  477.                                     // LANBIOS must be there if anything is
  478.     printf("LANBIOS........installed\n");
  479.  
  480.     if (lannode[0].wFlags & D_redir)
  481.         printf("Redirector.....installed\n");
  482.     else
  483.         printf("Redirector.not.installed\n");
  484.  
  485.     if (lannode[0].wFlags & D_server)
  486.         printf("Server.........installed\n");
  487.     else
  488.         printf("Server.....not.installed\n");
  489.  
  490.     if (lannode[0].wFlags & D_lanpup)
  491.         printf("LANPUP.........installed\n");
  492.     else
  493.         printf("LANPUP.....not.installed\n");
  494.  
  495.                                     // Report disposition of message service
  496.     NOSGetMsgFlag(&i);        
  497.     if (i == -1)
  498.         FATAL(E_GETMSGFLAG);        // Unexpected error
  499.  
  500.     printf("Messages.will.%s\n", 
  501.                 (i & MPB_beep)?"......BEEP":".not.BEEP");
  502.     printf("Messages.will.%s\n", 
  503.                 (i & MPB_auto_pop_up)?".....POP UP":".not.POP UP");
  504.  
  505.  
  506.         //
  507.         // Now report on the network servers. Sometimes this can be
  508.         // misleading, since a server can go down and LANtastic won't
  509.         // figure that out for a little while.
  510.         //
  511.  
  512.                                     // Report what we are logged into
  513.     printf("\nActive servers you are logged into:\n");
  514.  
  515.     i = 0;
  516.     while (NOSGetLogin(&i, &cpServer[2], &j) != -1){
  517.  
  518.         if (NOSGetUserName(&i, cpUsername, &j) != -1)
  519.             printf("\n\t%.16s as %s on adapter #%d\n", 
  520.                         &cpServer[2], cpUsername, j);
  521.  
  522.                                     // Prefix server name with \\
  523.         cpServer[0] = cpServer[1] = '\\';    
  524.  
  525.                                     // Report status of physical printers
  526.         printf("\t\tPrinter ports:\n");
  527.         while (NOSGetStatus(&j, &ps, cpServer) != -1){
  528.                                     // Only list enabled ports
  529.             if (ps.PS_state.PS_state_value != 0)
  530.                 printf("\t\t\t%-12s\t%s\n", printers[j-1], "ENABLED");
  531.         }
  532.  
  533.                                     // Report status of printer streams
  534.         j = 0;
  535.         printf("\t\tPrinter streams:\n");
  536.         while (NOSGetStreamInfo(&j, &s, cpServer) != -1){
  537.             if (s.LS_template[0] != '@')
  538.                 continue;            // Stream is not in use
  539.         
  540.                                     // Print stream info
  541.             printf("\t\t\t%.12s\t%s\n", s.LS_template, 
  542.                             (s.LS_queue == 0)? "DISABLED" : "ENABLED");
  543.         }
  544.  
  545.         i++;                         // Increment index for next loop
  546.         b = TRUE;                    // Show we found at least one
  547.     };
  548.  
  549.     if (!b)
  550.         printf("\n\tNone\n");        // Not logged into any servers
  551.     
  552.                                     // Report other available servers
  553.     printf("\nOther active servers available for login:\n\n");
  554.     b = FALSE;
  555.     i = 0;
  556.     while (NOSGetServer(&i, cpServer, &j) != -1){
  557.         b = TRUE;                    // Show we found one
  558.         printf("\t%.16son adapter #%d\n", cpServer, j);
  559.         i++;                         // Increment index
  560.     };
  561.  
  562.     if (!b)
  563.         printf("\tNone\n");            // No available servers
  564.  
  565.                                     // Report other workstations
  566.     printf("\nOther active workstations:\n\n");
  567.     delay(5000);                    // Delay 5 seconds for all replies.
  568.     getnodetable();                    // Update our node table.
  569.     b = FALSE;
  570.     for (i = 1; i < D_NODES; i++){    // Don't list ourselves, and ignore 
  571.                                     // empty entries and servers. They
  572.                                     // were already reported.
  573.         if((lannode[i].cpName[0] != '\0') && !(lannode[i].wFlags & D_server)){
  574.             printf("\t%.16s\n", lannode[i].cpName);
  575.             b = TRUE;
  576.         }
  577.     }
  578.  
  579.     if (!b)
  580.         printf("\tNone\n");            // No other workstations found
  581. }
  582.  
  583.     //
  584.     //    GETNODETABLE
  585.     //
  586.     //    Copies the current network node table from the background copy
  587.     //    maintained by LANRES.
  588.     //
  589.  
  590. void getnodetable()
  591. {
  592.     void far *fp = (void far *)&lannode[1];
  593.  
  594.             // 
  595.             // Call LANRES via the TesSeRact library. 
  596.             // Pass in the pointer to the network node table. 
  597.             //
  598.     (void)TsCallUserProc(TSRid, fp);
  599. }
  600.  
  601.     //
  602.     //    PARSECMD
  603.     //
  604.     //    Parse the LAN command line, return a pointer to the lancmd
  605.     //    table entry.
  606.     //
  607.  
  608. struct lancmd *parsecmd(cmd)
  609. char *cmd;
  610. {
  611.     struct lancmd *lc = &lancmd[0];
  612.     int i;
  613.  
  614.         // Try to find this command in the table
  615.  
  616.     while (lc->cpCmd != (char *)0)
  617.         if (stricmp(cmd, lc->cpCmd) == 0)
  618.             return(lc);
  619.         else
  620.             lc++;
  621.  
  622.     return(lc);
  623. }
  624.  
  625.     //
  626.     //    ARGIVAL
  627.     //
  628.     //    Find value of argument identified by argstr. For example,
  629.     //    if you want to extract the value 19 from the command switch
  630.     //    argument "/HOSTS=19", then call this function with argstr 
  631.     //    set to "/HOSTS" and it will return the value 19 if any of the
  632.     //    the other string parameters (the argv parameter) match either
  633.     //    "/HOSTS" or "/hosts" or "/HoSts" or "/HOSts" or...
  634.     //
  635.     //    The check for the "=" character is done within this routine.
  636.     //    The number of char *'s held in argv is specified by the value
  637.     //    of argc. 
  638.     //    
  639.     //    This function returns ARGVALERR if it cannot match argstr with
  640.     //    the leading characters of the other arguments. This means that
  641.     //    you cannot obtain a paramter value of ARGVALERR from this routine.
  642.     //
  643.     //    The other parameters to this function are usually argc,
  644.     //    argv and envp as inherited by the program. If others are 
  645.     //    used, then they must be of the same format.
  646.     //
  647.  
  648. int argival(argstr, argc, argv)
  649. char *argstr;
  650. int argc;
  651. char *argv[];
  652. {
  653.     int i, len;
  654.  
  655.     if (argc < 1)
  656.         return (ARGVALERR);            // Nothing to search through
  657.  
  658.     len = strlen(argstr);            // Length of string to match
  659.  
  660.     for (i = 0; i < argc; i++){
  661.         if ((strnicmp(argstr, argv[i], len) == 0)
  662.             && (argv[i][len] == '='))
  663.                                     // Found a match
  664.             return(atoi(&argv[i][len+1]));
  665.     }
  666.     return(ARGVALERR);                // No match
  667.  
  668. }
  669.  
  670.     //
  671.     //    ARGSVAL
  672.     //
  673.     //    Find string value of argument identified by argstr. For example,
  674.     //    if you want to extract the string ERIC from the command switch
  675.     //    argument "/HOST=ERIC", then call this function with argstr 
  676.     //    set to "/HOSTS" and it will return the string ERIC if any of the
  677.     //    the other string parameters (the argv parameter) match either
  678.     //    "/HOST" or "/host" or "/HoSt" or "/HOSt" or...
  679.     //
  680.     //    The check for the "=" character is done within this routine.
  681.     //    The number of char *'s held in argv is specified by the value
  682.     //    of argc. 
  683.     //    
  684.     //    This function returns NULL if it cannot match argstr with
  685.     //    the leading characters of the other arguments. 
  686.     //
  687.     //    The other parameters to this function are usually argc,
  688.     //    argv and envp as inherited by the program. If others are 
  689.     //    used, then they must be of the same format.
  690.     //
  691.  
  692. char *argsval(argstr, argc, argv)
  693. char *argstr;
  694. int argc;
  695. char *argv[];
  696. {
  697.     int i, len;
  698.  
  699.     if (argc < 1)
  700.         return (NULL);                // Nothing to search through
  701.  
  702.     len = strlen(argstr);            // Length of string to match
  703.  
  704.     for (i = 0; i < argc; i++){
  705.         if ((strnicmp(argstr, argv[i], len) == 0)
  706.             && (argv[i][len] == '='))
  707.                                     // Found a match
  708.             return(&argv[i][len+1]);
  709.     }
  710.     return(NULL);                    // No match
  711. }